package com.kuang.single;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

/**
 * Author: Zhang Dongwei
 * Date: 2022/3/16 16:41
 * 懒汉式单例模式
 * 道高一尺，魔高一丈
 */
public class LazyMan {

    private static boolean zhangdongwei = false;

    private LazyMan(){

        synchronized (LazyMan.class){
            if(zhangdongwei == false){
                zhangdongwei = true;
            }else {
                throw new RuntimeException("不要试图使用反射破坏异常");
            }
        }

//        System.out.println(Thread.currentThread().getName()+"ok");
    }

    private volatile static LazyMan lazyMan; // 用的时候再加载对象

    // 双重检测锁模式的 懒汉式单例 DCL 懒汉式
    public static LazyMan getInstance(){
        if(lazyMan == null){
            synchronized (LazyMan.class){
                if(lazyMan == null){
                    lazyMan = new LazyMan(); // 不是一个原子性操作
                    /**
                     * 1. 分配内存空间
                     * 2. 执行构造方法，初始化对象
                     * 3. 把这个对象指向这个空间
                     * 故可能发生指令重排
                     */
                }
            }
        }
        return lazyMan;
    }
    // 单线程下，没问题，但是多线程并发有问题
    // 反射
    public static void main(String[] args) throws Exception {
//        for (int i = 0; i < 10; i++) {
//            new Thread(()->{
//                lazyMan.getInstance();
//            }).start();
//        }
//        LazyMan instance = LazyMan.getInstance();

        Field zhangdongwei = LazyMan.class.getDeclaredField("zhangdongwei");
        zhangdongwei.setAccessible(true);

        Constructor<LazyMan> declaredConstructor = LazyMan.class.getDeclaredConstructor(null);
        declaredConstructor.setAccessible(true);
        LazyMan instance = declaredConstructor.newInstance();

        zhangdongwei.set(instance, false);

        LazyMan instance2 = declaredConstructor.newInstance();

        System.out.println(instance);
        System.out.println(instance2);
    }
}
